package com.xexun.gpstracker.common;

import android.content.Context;
import android.location.Location;
import android.util.Log;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.xexun.gpstracker.inter.CommCallback;
import com.xexun.gpstracker.inter.LocationProvider;
import com.xexun.gpstracker.inter.NotifyCallback;
import com.xexun.gpstracker.inter.NotifyCallbackEx;
import com.xexun.gpstracker.util.CommUtil;
import com.xexun.gpstracker.vo.GTLatLng;

import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by HH
 * Date: 2015/6/24 0024
 * Time: 下午 7:51
 */
public class LocationProviderAMAP implements LocationProvider,AMapLocationListener, GeocodeSearch.OnGeocodeSearchListener {
    private AMapLocationClient locationClient;

    private Context context;

    private static Map<String, NotifyCallback> callbackMap;
    private static LinkedList<NotifyCallback> callbackList;
    private static LinkedList<NotifyCallbackEx> callbackListEx;
    private static LinkedList<CommCallback> commCallbackList;

    public static boolean isLocationing = false;

    private static LocationProviderAMAP instance;

    public static LocationProviderAMAP getInstance(Context context) {
        if (instance == null) {
            instance = new LocationProviderAMAP(context);
        }
        return instance;
    }

    private LocationProviderAMAP(Context context) {
        this.context = context;
    }

    public void startLocation() {
        locationClient = new AMapLocationClient(context);
        locationClient.setLocationListener(this);
        //初始化定位参数
        AMapLocationClientOption mLocationOption = new AMapLocationClientOption();
        //设置定位模式为高精度模式，Battery_Saving为低功耗模式，Device_Sensors是仅设备模式
        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        //设置是否返回地址信息（默认返回地址信息）
        mLocationOption.setNeedAddress(true);
        //设置是否只定位一次,默认为false
        mLocationOption.setOnceLocation(true);
        //设置是否强制刷新WIFI，默认为强制刷新
        mLocationOption.setWifiActiveScan(true);
        //设置是否允许模拟位置,默认为false，不允许模拟位置
        mLocationOption.setMockEnable(false);
        //设置定位间隔,单位毫秒,默认为2000ms
        mLocationOption.setInterval(2000);
        //给定位客户端对象设置定位参数
        locationClient.setLocationOption(mLocationOption);
        //启动定位
        locationClient.startLocation();
        isLocationing = true;
    }

    public void startLocation(NotifyCallback callback) {
        if (callbackList == null) {
            callbackList = new LinkedList<>();
        }
        callbackList.add(callback);
        startLocation();
    }

    public void startLocation(NotifyCallbackEx callback) {
        if (callbackListEx == null) {
            callbackListEx = new LinkedList<>();
        }
        callbackListEx.add(callback);
        startLocation();
    }

    public LocationProvider setNotify(String key, NotifyCallback callback) {
        if (callbackMap == null) {
            callbackMap = new ConcurrentHashMap<>();
        }
        callbackMap.put(key, callback);
        return this;
    }

    public void removeNotify(String key) {
        if (callbackMap != null) {
            callbackMap.remove(key);
        }
    }

    public void clearNotify() {
        if (callbackMap != null) {
            callbackMap.clear();
        }
    }

    public void stop() {
        if (locationClient != null) {
            locationClient.stopLocation();
            locationClient.onDestroy();
        }
        locationClient = null;
    }

    @Override
    public void onLocationChanged(AMapLocation loc) {
        if (loc == null) {
            return;
        }
        if (loc.getErrorCode() != 0) {
            Log.e(LocationProviderAMAP.class.getName(), "定位失败，错误码：" + loc.getErrorCode() + " 信息：" + loc.getErrorInfo());
            return;
        }
        GTLatLng latLng = new GTLatLng(loc.getLatitude(), loc.getLongitude());
        isLocationing = false;
        Log.d(Constants.TAG, "当前位置：" + latLng.getLatitude() + "," + latLng.getLongitude());
        if (callbackMap != null && !callbackMap.isEmpty()) {
            for (Map.Entry<String, NotifyCallback> entry : callbackMap.entrySet()) {
                try {
                    entry.getValue().execute(latLng);
                } catch (Exception e) {
                    Log.w(Constants.TAG, "回调出错，有可能是执行环境已改变", e);
                }
            }
        }
        if (CommUtil.isNotEmpty(callbackList)) {
            NotifyCallback callback;
            while ((callback = callbackList.poll()) != null) {
                try {
                    callback.execute(latLng);
                } catch (Exception e) {
                    Log.w(Constants.TAG, "回调出错，有可能是执行环境已改变", e);
                }
            }
        }
        if (CommUtil.isNotEmpty(callbackListEx)) {
            NotifyCallbackEx callback;
            while ((callback = callbackListEx.poll()) != null) {
                try {
                    callback.execute((Location)loc);
                } catch (Exception e) {
                    Log.w(Constants.TAG, "回调出错，有可能是执行环境已改变", e);
                }
            }
        }
        stop();
    }

    @Override
    public void geoCodeSearch(GTLatLng latLng, CommCallback callback) {
        if (commCallbackList == null) {
            commCallbackList = new LinkedList<>();
        }
        commCallbackList.add(callback);

        GeocodeSearch mSearch = new GeocodeSearch(context);
        mSearch.setOnGeocodeSearchListener(this);
        LatLonPoint pt = new LatLonPoint(latLng.latitude, latLng.longitude);
        //latLonPoint参数表示一个Latlng，第二参数表示范围多少米，GeocodeSearch.AMAP表示是国测局坐标系还是GPS原生坐标系
        RegeocodeQuery query = new RegeocodeQuery(pt, 5, GeocodeSearch.AMAP);
        mSearch.getFromLocationAsyn(query);
    }

    @Override
    public void onRegeocodeSearched(RegeocodeResult result, int i) {
        if (i == 1000) {
            if (CommUtil.isNotEmpty(commCallbackList)) {
                CommCallback callback;
                while ((callback = commCallbackList.poll()) != null) {
                    try {
                        callback.execute(result.getRegeocodeAddress().getFormatAddress());
                    } catch (Exception e) {
                        Log.w(Constants.TAG, "回调出错，有可能是执行环境已改变", e);
                    }
                }
            }
        } else {
            Log.e(LocationProviderAMAP.class.getName(), "反编码地理位置失败！返回码：" + i);
        }
    }

    @Override
    public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {

    }
}
